package com.yuanss.backenddemo.auth.filter;

import com.yuanss.backenddemo.auth.token.JwtToken;
import com.yuanss.backenddemo.constant.JwtConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author yuanss
 * @version 1.0
 * @description jwt过滤器
 * @date 2024/6/12 20:32:56
 * 执行顺序
 * 1. preHandle() 方法执行
 * 2. isAccessAllowed() 方法执行
 */
@Slf4j
public class JwtFilter extends BasicHttpAuthenticationFilter {
    /**
     * 拦截器的前置
     */
    @Override
    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        // 跨域处理
        res.setHeader("Access-control-Allow-Origin", req.getHeader("Origin"));
        res.setHeader("Access-control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
        res.setHeader("Access-control-Allow-Headers", req.getHeader("Access-Control-Request-Headers"));
        // 跨域时会首先发送一个option请求，这里我们给option请求直接返回正常状态
        if (req.getMethod().equals(RequestMethod.OPTIONS.name())) {
            res.setStatus(HttpStatus.OK.value());
            return false;
        }
        return super.preHandle(request, response);
    }

    /**
     * preHandle
     * 根据条件判断去去执行isLoginAttempt和executeLogin方法
     */
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        /**
         * 先去调用 isLoginAttempt方法 字面意思就是是否尝试登陆 如果为true
         * 执行executeLogin方法
         */
        // todo 逻辑待完善
        if (isLoginAttempt(request, response)) {
            executeLogin(request, response);
            return true;
        }
        return true;
    }


    /**
     * 这里我们只是简单去做一个判断请求头中的token信息是否为空
     * 如果没有我们想要的请求头信息则直接返回false
     */
    @Override
    protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) {
        HttpServletRequest req = (HttpServletRequest) request;
        String token = req.getHeader(JwtConstant.TOKEN_HEADER);
        return token != null;
    }


    /**
     * 执行登陆
     * 因为已经判断token不为空了,所以直接执行登陆逻辑
     * 将token放入JwtToken类中去
     * 然后getSubject方法是调用到了MyRealm的执行方法
     */
    @Override
    protected boolean executeLogin(ServletRequest request, ServletResponse response) {
        HttpServletRequest req = (HttpServletRequest) request;
        String token = req.getHeader(JwtConstant.TOKEN_HEADER);
        JwtToken jwtToken = new JwtToken(token);
        // 交给自定义的realm对象去认证和授权
        getSubject(request, response).login(jwtToken);
        return true;
    }
}
